001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
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: package org.outerj.daisy.frontend.editor;
017:
018: import org.apache.excalibur.store.Store;
019: import org.apache.excalibur.source.Source;
020: import org.apache.excalibur.source.SourceResolver;
021: import org.apache.avalon.framework.service.ServiceManager;
022: import org.apache.avalon.framework.context.Context;
023: import org.apache.avalon.framework.logger.Logger;
024: import org.apache.xmlbeans.XmlOptions;
025: import org.outerj.daisy.frontend.util.CacheHelper;
026: import org.outerj.daisy.xmlutil.LocalSAXParserFactory;
027: import org.outerx.daisy.x10Parteditor.PartEditorDocument;
028:
029: import java.io.InputStream;
030: import java.util.Map;
031: import java.util.HashMap;
032: import java.util.Collections;
033:
034: /**
035: * Manages the construction of {@link PartEditor}s for parts, based on configuration.
036: */
037: public class PartEditorManager {
038: private static final String STORE_PREFIX = PartEditorManager.class
039: .getName();
040:
041: public static PartEditor getPartEditor(String partTypeName,
042: ServiceManager serviceManager, Context context,
043: Logger logger) throws Exception {
044: SourceResolver sourceResolver = null;
045: Source source = null;
046: Store store = null;
047: try {
048: sourceResolver = (SourceResolver) serviceManager
049: .lookup(SourceResolver.ROLE);
050: source = sourceResolver
051: .resolveURI("wikidata:/resources/parteditors/"
052: + partTypeName + ".xml");
053: if (!source.exists()) {
054: return null;
055: } else {
056: store = (Store) serviceManager
057: .lookup(Store.TRANSIENT_STORE);
058: PartEditorInfo partEditorInfo = (PartEditorInfo) CacheHelper
059: .getFromCache(store, source, STORE_PREFIX);
060: if (partEditorInfo == null) {
061: partEditorInfo = buildPartEditorInfo(source, logger);
062: CacheHelper.setInCache(store, partEditorInfo,
063: source, STORE_PREFIX);
064: }
065:
066: if (partEditorInfo.isValid()) {
067: return partEditorInfo.getBuilder().getPartEditor(
068: partEditorInfo.getProperties(),
069: serviceManager, context);
070: }
071: }
072: } finally {
073: if (source != null)
074: sourceResolver.release(source);
075: if (sourceResolver != null)
076: serviceManager.release(sourceResolver);
077: if (store != null)
078: serviceManager.release(store);
079: }
080: return null;
081: }
082:
083: private static PartEditorInfo buildPartEditorInfo(Source source,
084: Logger logger) {
085: PartEditorDocument partEditorDocument;
086: try {
087: InputStream is = null;
088: try {
089: is = source.getInputStream();
090: XmlOptions xmlOptions = new XmlOptions()
091: .setLoadUseXMLReader(LocalSAXParserFactory
092: .newXmlReader());
093: partEditorDocument = PartEditorDocument.Factory.parse(
094: is, xmlOptions);
095: } finally {
096: if (is != null)
097: is.close();
098: }
099:
100: String className = partEditorDocument.getPartEditor()
101: .getClass1();
102: if (className == null)
103: throw new Exception(
104: "Missing class attribute for partEditor specification in "
105: + source.getURI());
106:
107: Class clazz;
108: try {
109: clazz = PartEditorManager.class.getClassLoader()
110: .loadClass(className);
111: } catch (ClassNotFoundException e) {
112: throw new Exception("Class for partEditor not found: "
113: + className + " specified in "
114: + source.getURI());
115: }
116:
117: if (!PartEditorFactory.class.isAssignableFrom(clazz)) {
118: throw new Exception(
119: "Class specified for part editor is not a "
120: + PartEditorFactory.class.getName()
121: + " at " + source.getURI());
122: }
123:
124: PartEditorFactory factory = (PartEditorFactory) clazz
125: .newInstance();
126:
127: Map<String, String> properties = new HashMap<String, String>();
128: PartEditorDocument.PartEditor.Properties propertiesXml = partEditorDocument
129: .getPartEditor().getProperties();
130: if (propertiesXml != null) {
131: for (PartEditorDocument.PartEditor.Properties.Entry entry : propertiesXml
132: .getEntryList()) {
133: String key = entry.getKey();
134: if (key != null) {
135: properties.put(key, entry.getStringValue());
136: }
137: }
138: }
139:
140: return new PartEditorInfo(factory, Collections
141: .unmodifiableMap(properties), true);
142: } catch (Throwable e) {
143: logger.error("Error in part editor specification at "
144: + source.getURI(), e);
145: return new PartEditorInfo(null, null, false);
146: }
147: }
148:
149: static class PartEditorInfo {
150: private PartEditorFactory factory;
151: private Map properties;
152: private boolean valid;
153:
154: public PartEditorInfo(PartEditorFactory factory,
155: Map properties, boolean valid) {
156: this .factory = factory;
157: this .properties = properties;
158: this .valid = valid;
159:
160: if (valid && (factory == null || properties == null)) {
161: throw new IllegalArgumentException(
162: "if valid argument is true, the other arguments cannot be null");
163: }
164: }
165:
166: public PartEditorFactory getBuilder() {
167: return factory;
168: }
169:
170: public Map getProperties() {
171: return properties;
172: }
173:
174: public boolean isValid() {
175: return valid;
176: }
177: }
178: }
|