001/* 002 * Copyright 2022 Anyware Services 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 */ 016package org.ametys.web.service; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.avalon.framework.parameters.Parameters; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.avalon.framework.service.Serviceable; 028import org.apache.cocoon.acting.AbstractAction; 029import org.apache.cocoon.environment.ObjectModelHelper; 030import org.apache.cocoon.environment.Redirector; 031import org.apache.cocoon.environment.Request; 032import org.apache.excalibur.source.Source; 033import org.apache.excalibur.source.SourceResolver; 034 035import org.ametys.web.WebConstants; 036import org.ametys.web.repository.page.ZoneItem; 037 038/** 039 * This action export the wrapping XSLT URI for a service.<br> 040 * Service negociation will be performed with the given URI: if service.xsl is asked, service-[serviceId].xsl will be looked up first. 041 * 042 * This action needs the parameter <code>path</code> pointing the default path to the XSL. 043 */ 044public class GetServiceWrapperContextAction extends AbstractAction implements Serviceable 045{ 046 /** The source resolver */ 047 protected SourceResolver _srcResolver; 048 049 @Override 050 public void service(ServiceManager manager) throws ServiceException 051 { 052 _srcResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 053 } 054 055 @Override 056 public Map<String, String> act(Redirector redirector, org.apache.cocoon.environment.SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 057 { 058 Request request = ObjectModelHelper.getRequest(objectModel); 059 060 HashMap<String, String> result = new HashMap<>(); 061 String uri = parameters.getParameter("path"); 062 String wrapperURI = getWrapperURI(request, uri); 063 064 result.put("wrapper-uri", wrapperURI); 065 return result; 066 } 067 068 /** 069 * Compute the wrapping URI for the current service. 070 * @param request the current Request. 071 * @param uri the default uri. 072 * @return the wrapper XSLT URI. 073 * @throws IOException if an error occurs while resolving Sources. 074 */ 075 protected String getWrapperURI(Request request, String uri) throws IOException 076 { 077 String wrapperURI = null; 078 079 ZoneItem zoneItem = (ZoneItem) request.getAttribute(WebConstants.REQUEST_ATTR_ZONEITEM); 080 String serviceId = zoneItem.getServiceId(); 081 082 // Ex : skin://stylesheets/service/_wrapper/service-[serviceId].xsl 083 int index = uri.indexOf(".xsl"); 084 wrapperURI = "skin://" + uri.substring(0, index) + "-" + serviceId + ".xsl"; 085 Source src = _srcResolver.resolveURI(wrapperURI); 086 if (!src.exists()) 087 { 088 if (getLogger().isDebugEnabled()) 089 { 090 getLogger().debug("Failed to find a file in the skin for '" + wrapperURI + "'. Rollink back to skin protocol."); 091 } 092 093 // Ex : skin://stylesheets/service/_wrapper/service.xsl 094 wrapperURI = "skin://" + uri; 095 src = _srcResolver.resolveURI(wrapperURI); 096 if (!src.exists()) 097 { 098 if (getLogger().isDebugEnabled()) 099 { 100 getLogger().debug("Failed to find a file in the skin for '" + wrapperURI + "'. Rollink back to context protocol."); 101 } 102 103 wrapperURI = _getWrapperURIFromSources(request, uri); 104 } 105 } 106 107 return wrapperURI; 108 } 109 110 /** 111 * Get wrapper URI from sources 112 * @param request the current Request. 113 * @param uri the default uri. 114 * @return the wrapper XSLT URI. 115 * @throws IOException if an error occurs while resolving Sources. 116 */ 117 protected String _getWrapperURIFromSources(Request request, String uri) throws IOException 118 { 119 for (String wrapperURI : getSourceURIs(request, uri)) 120 { 121 Source src = _srcResolver.resolveURI(wrapperURI); 122 if (!src.exists()) 123 { 124 if (getLogger().isDebugEnabled()) 125 { 126 getLogger().debug("Failed to find a stylesheet at '" + wrapperURI + "'."); 127 } 128 } 129 else 130 { 131 return wrapperURI; 132 } 133 } 134 135 return null; 136 } 137 138 /** 139 * Get the source URI for wrapped service 140 * @param request The request 141 * @param requestedURI The requested URI 142 * @return the wrapped URI 143 */ 144 protected List<String> getSourceURIs (Request request, String requestedURI) 145 { 146 List<String> sourceURIs = new ArrayList<>(); 147 148 ZoneItem zoneItem = (ZoneItem) request.getAttribute(WebConstants.REQUEST_ATTR_ZONEITEM); 149 String serviceId = zoneItem.getServiceId(); 150 151 // Ex: context://WEB-INF/stylesheets/service/_wrapper/service-[cType].xsl 152 int index = requestedURI.indexOf(".xsl"); 153 154 sourceURIs.add("context://WEB-INF/" + requestedURI.substring(0, index) + "-" + serviceId + ".xsl"); 155 156 sourceURIs.add("context://WEB-INF/" + requestedURI); 157 158 sourceURIs.add("workspace:" + request.getAttribute("workspaceName") + "://" + requestedURI); 159 160 return sourceURIs; 161 162 } 163}