001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.persistence;
018:
019: import java.io.InputStream;
020: import java.io.OutputStream;
021: import java.io.OutputStreamWriter;
022: import java.io.Writer;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.Map;
026: import java.util.Map.Entry;
027:
028: import org.apache.avalon.framework.activity.Initializable;
029: import org.apache.avalon.framework.component.Component;
030: import org.apache.avalon.framework.configuration.Configurable;
031: import org.apache.avalon.framework.configuration.Configuration;
032: import org.apache.avalon.framework.configuration.ConfigurationException;
033: import org.apache.avalon.framework.logger.AbstractLogEnabled;
034: import org.apache.avalon.framework.service.ServiceException;
035: import org.apache.avalon.framework.service.ServiceManager;
036: import org.apache.avalon.framework.service.Serviceable;
037: import org.apache.avalon.framework.thread.ThreadSafe;
038: import org.apache.cocoon.components.source.SourceUtil;
039: import org.apache.cocoon.portal.profile.ProfileLS;
040: import org.apache.cocoon.portal.util.ReferenceFieldHandler;
041: import org.apache.excalibur.source.Source;
042: import org.apache.excalibur.source.SourceResolver;
043: import org.exolab.castor.mapping.Mapping;
044: import org.exolab.castor.mapping.MappingException;
045: import org.exolab.castor.xml.Marshaller;
046: import org.exolab.castor.xml.Unmarshaller;
047: import org.xml.sax.InputSource;
048:
049: /**
050: * This is a component converting the profiles (= object tree) to XML and vice-versa
051: * using Castor. It could be used to persist objects as a XML representation.
052: *
053: * In order to work properly the methods provided by this interface require some
054: * parameters:
055: * objectmap : containing a map of objects for resolving references during load
056: * profiletype: specifying the mapping (e.g. in the portal this is one of layout, copletinstancedata, copletdata or copletbasedate)
057: * suppressXSIType: Sets whether or not the xsi:type attributes should appear on the marshalled document.
058: *
059: * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
060: * @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
061: * @author <a href="mailto:bluetkemeier@s-und-n.de">Björn Lütkemeier</a>
062: *
063: * @version CVS $Id: CastorSourceConverter.java 433543 2006-08-22 06:22:54Z crossley $
064: */
065: public class CastorSourceConverter extends AbstractLogEnabled implements
066: Component, Serviceable, Configurable, Initializable, ThreadSafe {
067:
068: public static final String ROLE = CastorSourceConverter.class
069: .getName();
070:
071: private Map mappingSources = new HashMap();
072: private ServiceManager manager;
073: private Map mappings = new HashMap();
074: private boolean defaultSuppressXSIType;
075: private boolean defaultValidateUnmarshalling;
076:
077: public Object getObject(InputStream stream, Map parameters)
078: throws ConverterException {
079: try {
080: ReferenceFieldHandler.setObjectMap((Map) parameters
081: .get(ProfileLS.PARAMETER_OBJECTMAP));
082: Unmarshaller unmarshaller = (Unmarshaller) ((Object[]) this .mappings
083: .get(parameters
084: .get(ProfileLS.PARAMETER_PROFILETYPE)))[1];
085: Object result = unmarshaller.unmarshal(new InputSource(
086: stream));
087: stream.close();
088: return result;
089: } catch (Exception e) {
090: throw new ConverterException(e.getMessage(), e);
091: } finally {
092: ReferenceFieldHandler.clearObjectMap();
093: }
094: }
095:
096: public void storeObject(OutputStream stream, Map parameters,
097: Object object) throws ConverterException {
098: Writer writer = new OutputStreamWriter(stream);
099: try {
100: Marshaller marshaller = new Marshaller(writer);
101: marshaller.setMapping((Mapping) ((Object[]) this .mappings
102: .get(parameters
103: .get(ProfileLS.PARAMETER_PROFILETYPE)))[0]);
104: boolean suppressXSIType = this .defaultSuppressXSIType;
105: Boolean value = (Boolean) parameters.get("suppressXSIType");
106: if (value != null) {
107: suppressXSIType = value.booleanValue();
108: }
109: marshaller.setSuppressXSIType(suppressXSIType);
110: marshaller.marshal(object);
111: writer.close();
112: } catch (MappingException e) {
113: throw new ConverterException("Can't create Unmarshaller", e);
114: } catch (Exception e) {
115: throw new ConverterException(e.getMessage(), e);
116: }
117: }
118:
119: /**
120: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
121: */
122: public void service(ServiceManager manager) throws ServiceException {
123: this .manager = manager;
124: }
125:
126: /**
127: * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
128: */
129: public void configure(Configuration config)
130: throws ConfigurationException {
131: Configuration[] children = config.getChildren("mapping-source");
132: for (int i = 0; i < children.length; i++) {
133: Configuration mappingSource = children[i];
134: this .mappingSources.put(mappingSource
135: .getAttribute("source"), mappingSource.getValue());
136: }
137: this .defaultSuppressXSIType = config
138: .getChild("suppressXSIType").getValueAsBoolean(false);
139: this .defaultValidateUnmarshalling = config.getChild(
140: "validate-on-unmarshalling").getValueAsBoolean(false);
141: }
142:
143: /**
144: * @see org.apache.avalon.framework.activity.Initializable#initialize()
145: */
146: public void initialize() throws Exception {
147: SourceResolver resolver = (SourceResolver) manager
148: .lookup(SourceResolver.ROLE);
149: Source source = null;
150: try {
151: Entry entry;
152: String name;
153: String mappingSource;
154: Mapping mapping;
155: Iterator iterator = this .mappingSources.entrySet()
156: .iterator();
157: while (iterator.hasNext()) {
158: entry = (Map.Entry) iterator.next();
159: name = (String) entry.getKey();
160: mappingSource = (String) entry.getValue();
161:
162: source = resolver.resolveURI(mappingSource);
163: mapping = new Mapping();
164: mapping.loadMapping(SourceUtil.getInputSource(source));
165:
166: // create unmarshaller
167: final Unmarshaller unmarshaller = new Unmarshaller(
168: mapping);
169: unmarshaller
170: .setValidation(this .defaultValidateUnmarshalling);
171: this .mappings.put(name, new Object[] { mapping,
172: unmarshaller });
173: }
174: } finally {
175: if (source != null) {
176: resolver.release(source);
177: }
178: manager.release(resolver);
179: }
180: }
181: }
|