/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.portal.profile.impl; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.components.persistence.CastorSourceConverter; import org.apache.cocoon.portal.profile.ProfileLS; import org.apache.cocoon.util.NetUtils; import org.apache.cocoon.xml.dom.DOMUtil; import org.apache.excalibur.source.ModifiableSource; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceResolver; import org.apache.excalibur.source.SourceValidity; import org.apache.excalibur.xml.sax.SAXParser; import org.apache.excalibur.xml.xpath.XPathProcessor; import org.w3c.dom.Element; /** * This implementation uses Castor to load/save the profiles. * * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a> * * @version CVS $Id$ */ public class MapProfileLS extends AbstractLogEnabled implements Component, Serviceable, ProfileLS, ThreadSafe, Disposable { /** The component manager */ protected ServiceManager manager; /** The XPath Processor */ protected XPathProcessor xpathProcessor; /* (non-Javadoc) * @see org.apache.avalon.framework.activity.Disposable#dispose() */ public void dispose() { if ( this.manager != null ) { this.manager.release( this.xpathProcessor ); this.xpathProcessor = null; this.manager = null; } } /* (non-Javadoc) * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) */ public void service(ServiceManager manager) throws ServiceException { this.manager = manager; this.xpathProcessor = (XPathProcessor)this.manager.lookup(XPathProcessor.ROLE); } protected String getURI(Map keyMap) throws Exception { final StringBuffer buffer = new StringBuffer(); Iterator iter = keyMap.entrySet().iterator(); boolean pars = false; boolean first = true; while ( iter.hasNext() ) { final Map.Entry entry = (Entry) iter.next(); final String append = entry.getValue().toString(); if ( pars ) { if ( first ) { first = false; if ( buffer.toString().indexOf('?') == -1 ) { buffer.append('?'); } else { buffer.append('&'); } } else { buffer.append('&'); } buffer.append(entry.getKey().toString()); buffer.append('='); } else { if ( !first && !"?".equals(append) ) { buffer.append('/'); } first = false; } if ( "?".equals(append) ) { first = true; pars = true; } else { buffer.append(append); } } return buffer.toString(); } protected StringBuffer getSaveURI(Map keyMap) throws Exception { final StringBuffer buffer = new StringBuffer(this.getURI(keyMap)); return buffer; } /* (non-Javadoc) * @see org.apache.cocoon.portal.profile.ProfileLS#loadProfile(java.lang.Object) */ public Object loadProfile(Object key, Map parameters) throws Exception { final Map keyMap = (Map) key; final String uri = this.getURI( keyMap ); Source source = null; CastorSourceConverter converter = null; SourceResolver resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); try { source = resolver.resolveURI(uri); converter = (CastorSourceConverter) this.manager.lookup(CastorSourceConverter.ROLE); return converter.getObject(source.getInputStream(), parameters); } finally { if ( resolver != null ) { resolver.release(source); } manager.release(converter); manager.release(resolver); } } /* (non-Javadoc) * @see org.apache.cocoon.portal.profile.ProfileLS#saveProfile(java.lang.Object, java.lang.Object) */ public void saveProfile(Object key, Map parameters, Object profile) throws Exception { final Map keyMap = (Map) key; final String uri = this.getURI( keyMap ); // first test: modifiable source? SourceResolver resolver = null; CastorSourceConverter converter = null; Source source = null; try { resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); source = resolver.resolveURI(uri); if ( source instanceof ModifiableSource ) { converter = (CastorSourceConverter) this.manager.lookup(CastorSourceConverter.ROLE); converter.storeObject( ((ModifiableSource)source).getOutputStream(), parameters, profile); return; } } finally { if ( resolver != null ) { resolver.release(source); } manager.release(converter); manager.release(resolver); source = null; converter = null; resolver = null; } final StringBuffer buffer = this.getSaveURI( keyMap ); SAXParser parser = null; try { resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); converter = (CastorSourceConverter) this.manager.lookup(CastorSourceConverter.ROLE); ByteArrayOutputStream writer = new ByteArrayOutputStream(); converter.storeObject(writer, parameters, profile); buffer.append("&content="); try { buffer.append(NetUtils.encode(writer.toString(), "utf-8")); } catch (UnsupportedEncodingException uee) { // ignore this as utf-8 is always supported } source = resolver.resolveURI(buffer.toString()); parser = (SAXParser)this.manager.lookup(SAXParser.ROLE); Element element = DOMUtil.getDocumentFragment(parser, new InputStreamReader(source.getInputStream())).getOwnerDocument().getDocumentElement(); if (!DOMUtil.getValueOf(element, "descendant::sourceResult/execution", this.xpathProcessor).trim().equals("success")) { throw new IOException("Could not save profile: "+DOMUtil.getValueOf(element, "descendant::sourceResult/message", this.xpathProcessor)); } } finally { if ( resolver != null ) { resolver.release(source); } manager.release(parser); manager.release(converter); manager.release(resolver); } } /* (non-Javadoc) * @see org.apache.cocoon.portal.profile.ProfileLS#getValidity(java.lang.Object) */ public SourceValidity getValidity(Object key, Map parameters) { SourceResolver resolver = null; Source source = null; try { final Map keyMap = (Map) key; final String uri = this.getURI( keyMap ); resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); source = resolver.resolveURI(uri); return source.getValidity(); } catch (Exception e) { getLogger().warn(e.getMessage(), e); return null; } finally { if (resolver != null) { resolver.release(source); } manager.release(resolver); } } }