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.portal.profile.impl;
018:
019: import java.io.ByteArrayOutputStream;
020: import java.io.IOException;
021: import java.io.InputStreamReader;
022: import java.io.UnsupportedEncodingException;
023: import java.util.Iterator;
024: import java.util.Map;
025: import java.util.Map.Entry;
026:
027: import org.apache.avalon.framework.activity.Disposable;
028: import org.apache.avalon.framework.component.Component;
029: import org.apache.avalon.framework.logger.AbstractLogEnabled;
030: import org.apache.avalon.framework.service.ServiceException;
031: import org.apache.avalon.framework.service.ServiceManager;
032: import org.apache.avalon.framework.service.Serviceable;
033: import org.apache.avalon.framework.thread.ThreadSafe;
034: import org.apache.cocoon.components.persistence.CastorSourceConverter;
035: import org.apache.cocoon.portal.profile.ProfileLS;
036: import org.apache.cocoon.util.NetUtils;
037: import org.apache.cocoon.xml.dom.DOMUtil;
038: import org.apache.excalibur.source.ModifiableSource;
039: import org.apache.excalibur.source.Source;
040: import org.apache.excalibur.source.SourceResolver;
041: import org.apache.excalibur.source.SourceValidity;
042: import org.apache.excalibur.xml.sax.SAXParser;
043: import org.apache.excalibur.xml.xpath.XPathProcessor;
044: import org.w3c.dom.Element;
045:
046: /**
047: * This implementation uses Castor to load/save the profiles.
048: *
049: * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
050: *
051: * @version CVS $Id: MapProfileLS.java 433543 2006-08-22 06:22:54Z crossley $
052: */
053: public class MapProfileLS extends AbstractLogEnabled implements
054: Component, Serviceable, ProfileLS, ThreadSafe, Disposable {
055:
056: /** The component manager */
057: protected ServiceManager manager;
058:
059: /** The XPath Processor */
060: protected XPathProcessor xpathProcessor;
061:
062: /* (non-Javadoc)
063: * @see org.apache.avalon.framework.activity.Disposable#dispose()
064: */
065: public void dispose() {
066: if (this .manager != null) {
067: this .manager.release(this .xpathProcessor);
068: this .xpathProcessor = null;
069: this .manager = null;
070: }
071: }
072:
073: /* (non-Javadoc)
074: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
075: */
076: public void service(ServiceManager manager) throws ServiceException {
077: this .manager = manager;
078: this .xpathProcessor = (XPathProcessor) this .manager
079: .lookup(XPathProcessor.ROLE);
080: }
081:
082: protected String getURI(Map keyMap) throws Exception {
083: final StringBuffer buffer = new StringBuffer();
084: Iterator iter = keyMap.entrySet().iterator();
085: boolean pars = false;
086: boolean first = true;
087: while (iter.hasNext()) {
088: final Map.Entry entry = (Entry) iter.next();
089: final String append = entry.getValue().toString();
090: if (pars) {
091: if (first) {
092: first = false;
093: if (buffer.toString().indexOf('?') == -1) {
094: buffer.append('?');
095: } else {
096: buffer.append('&');
097: }
098: } else {
099: buffer.append('&');
100: }
101: buffer.append(entry.getKey().toString());
102: buffer.append('=');
103: } else {
104: if (!first && !"?".equals(append)) {
105: buffer.append('/');
106: }
107: first = false;
108: }
109: if ("?".equals(append)) {
110: first = true;
111: pars = true;
112: } else {
113: buffer.append(append);
114: }
115: }
116:
117: return buffer.toString();
118: }
119:
120: protected StringBuffer getSaveURI(Map keyMap) throws Exception {
121: final StringBuffer buffer = new StringBuffer(this
122: .getURI(keyMap));
123: return buffer;
124: }
125:
126: /* (non-Javadoc)
127: * @see org.apache.cocoon.portal.profile.ProfileLS#loadProfile(java.lang.Object)
128: */
129: public Object loadProfile(Object key, Map parameters)
130: throws Exception {
131: final Map keyMap = (Map) key;
132:
133: final String uri = this .getURI(keyMap);
134:
135: Source source = null;
136: CastorSourceConverter converter = null;
137: SourceResolver resolver = (SourceResolver) this .manager
138: .lookup(SourceResolver.ROLE);
139: try {
140: source = resolver.resolveURI(uri);
141: converter = (CastorSourceConverter) this .manager
142: .lookup(CastorSourceConverter.ROLE);
143:
144: return converter.getObject(source.getInputStream(),
145: parameters);
146: } finally {
147: if (resolver != null) {
148: resolver.release(source);
149: }
150: manager.release(converter);
151: manager.release(resolver);
152: }
153: }
154:
155: /* (non-Javadoc)
156: * @see org.apache.cocoon.portal.profile.ProfileLS#saveProfile(java.lang.Object, java.lang.Object)
157: */
158: public void saveProfile(Object key, Map parameters, Object profile)
159: throws Exception {
160: final Map keyMap = (Map) key;
161:
162: final String uri = this .getURI(keyMap);
163:
164: // first test: modifiable source?
165: SourceResolver resolver = null;
166: CastorSourceConverter converter = null;
167: Source source = null;
168: try {
169: resolver = (SourceResolver) this .manager
170: .lookup(SourceResolver.ROLE);
171: source = resolver.resolveURI(uri);
172: if (source instanceof ModifiableSource) {
173: converter = (CastorSourceConverter) this .manager
174: .lookup(CastorSourceConverter.ROLE);
175: converter.storeObject(((ModifiableSource) source)
176: .getOutputStream(), parameters, profile);
177: return;
178: }
179:
180: } finally {
181: if (resolver != null) {
182: resolver.release(source);
183: }
184: manager.release(converter);
185: manager.release(resolver);
186: source = null;
187: converter = null;
188: resolver = null;
189: }
190:
191: final StringBuffer buffer = this .getSaveURI(keyMap);
192:
193: SAXParser parser = null;
194: try {
195: resolver = (SourceResolver) this .manager
196: .lookup(SourceResolver.ROLE);
197: converter = (CastorSourceConverter) this .manager
198: .lookup(CastorSourceConverter.ROLE);
199:
200: ByteArrayOutputStream writer = new ByteArrayOutputStream();
201:
202: converter.storeObject(writer, parameters, profile);
203:
204: buffer.append("&content=");
205: try {
206: buffer.append(NetUtils.encode(writer.toString(),
207: "utf-8"));
208: } catch (UnsupportedEncodingException uee) {
209: // ignore this as utf-8 is always supported
210: }
211:
212: source = resolver.resolveURI(buffer.toString());
213:
214: parser = (SAXParser) this .manager.lookup(SAXParser.ROLE);
215: Element element = DOMUtil.getDocumentFragment(parser,
216: new InputStreamReader(source.getInputStream()))
217: .getOwnerDocument().getDocumentElement();
218: if (!DOMUtil.getValueOf(element,
219: "descendant::sourceResult/execution",
220: this .xpathProcessor).trim().equals("success")) {
221: throw new IOException("Could not save profile: "
222: + DOMUtil.getValueOf(element,
223: "descendant::sourceResult/message",
224: this .xpathProcessor));
225: }
226:
227: } finally {
228: if (resolver != null) {
229: resolver.release(source);
230: }
231: manager.release(parser);
232: manager.release(converter);
233: manager.release(resolver);
234: }
235: }
236:
237: /* (non-Javadoc)
238: * @see org.apache.cocoon.portal.profile.ProfileLS#getValidity(java.lang.Object)
239: */
240: public SourceValidity getValidity(Object key, Map parameters) {
241: SourceResolver resolver = null;
242: Source source = null;
243: try {
244: final Map keyMap = (Map) key;
245:
246: final String uri = this .getURI(keyMap);
247:
248: resolver = (SourceResolver) this .manager
249: .lookup(SourceResolver.ROLE);
250: source = resolver.resolveURI(uri);
251: return source.getValidity();
252: } catch (Exception e) {
253: getLogger().warn(e.getMessage(), e);
254: return null;
255: } finally {
256: if (resolver != null) {
257: resolver.release(source);
258: }
259: manager.release(resolver);
260: }
261: }
262:
263: }
|