001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.config.builder;
018:
019: import java.io.*;
020: import java.net.URL;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.compass.core.config.CompassConfiguration;
025: import org.compass.core.config.CompassEnvironment;
026: import org.compass.core.config.ConfigurationException;
027:
028: /**
029: * @author kimchy
030: */
031: public class SmartConfigurationBuilder implements ConfigurationBuilder {
032:
033: private static final Log log = LogFactory
034: .getLog(SmartConfigurationBuilder.class);
035:
036: /**
037: * Indicates that DTD validation should be used.
038: */
039: public static final int VALIDATION_DTD = 1;
040:
041: /**
042: * Indicates that XSD validation should be used.
043: */
044: public static final int VALIDATION_XSD = 2;
045:
046: /**
047: * The maximum number of lines the validation autodetection process should peek into
048: * a file looking for the <code>DOCTYPE</code> definition.
049: */
050: private static final int MAX_PEEK_LINES = 5;
051:
052: public void configure(String resource, CompassConfiguration config)
053: throws ConfigurationException {
054: InputStream stream = CompassEnvironment.class
055: .getResourceAsStream(resource);
056: if (stream == null) {
057: throw new ConfigurationException(
058: "Failed to open config resource [" + resource + "]");
059: }
060: int mode = detectValidationMode(stream, resource);
061: if (mode == VALIDATION_XSD) {
062: new SchemaConfigurationBuilder()
063: .configure(resource, config);
064: } else {
065: new DTDConfigurationBuilder().configure(resource, config);
066: }
067: }
068:
069: public void configure(URL url, CompassConfiguration config)
070: throws ConfigurationException {
071: InputStream stream;
072: try {
073: stream = url.openStream();
074: } catch (IOException e) {
075: throw new ConfigurationException("Failed to open url ["
076: + url.toExternalForm() + "]", e);
077: }
078: int mode = detectValidationMode(stream, url.toExternalForm());
079: if (mode == VALIDATION_XSD) {
080: new SchemaConfigurationBuilder().configure(url, config);
081: } else {
082: new DTDConfigurationBuilder().configure(url, config);
083: }
084: }
085:
086: public void configure(File file, CompassConfiguration config)
087: throws ConfigurationException {
088: InputStream stream;
089: try {
090: stream = new FileInputStream(file);
091: } catch (IOException e) {
092: throw new ConfigurationException(
093: "Could not find configuration file ["
094: + file.getAbsolutePath() + "]", e);
095: }
096: int mode = detectValidationMode(stream, file.getAbsolutePath());
097: if (mode == VALIDATION_XSD) {
098: new SchemaConfigurationBuilder().configure(file, config);
099: } else {
100: new DTDConfigurationBuilder().configure(file, config);
101: }
102: }
103:
104: private int detectValidationMode(InputStream stream,
105: String resourceName) {
106: //peek into the file to look for DOCTYPE
107: BufferedReader reader = null;
108: try {
109: reader = new BufferedReader(new InputStreamReader(stream));
110: boolean isDtdValidated = false;
111:
112: for (int x = 0; x < MAX_PEEK_LINES; x++) {
113: String line = reader.readLine();
114: if (line == null) {
115: // end of stream
116: break;
117: } else if (line.indexOf("DOCTYPE") > -1) {
118: isDtdValidated = true;
119: break;
120: }
121: }
122: return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
123: } catch (IOException ex) {
124: throw new ConfigurationException(
125: "Unable to determine validation mode for ["
126: + resourceName
127: + "]. Did you attempt to load directly from a SAX InputSource?",
128: ex);
129: } finally {
130: if (reader != null) {
131: try {
132: reader.close();
133: } catch (IOException ex) {
134: if (log.isWarnEnabled()) {
135: log.warn("Unable to close BufferedReader for ["
136: + resourceName + "].", ex);
137: }
138: }
139: }
140: }
141: }
142:
143: }
|