/* * Copyright 2003-2005 The Apache Software Foundation. * * Licensed 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.wsrp4j.commons.consumer.driver; import java.net.URL; import java.util.Hashtable; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import oasis.names.tc.wsrp.v1.intf.WSRPV1PortletManagementPortType; import oasis.names.tc.wsrp.v1.intf.WSRPV1RegistrationPortType; import oasis.names.tc.wsrp.v1.intf.WSRPV1ServiceDescriptionPortType; import oasis.names.tc.wsrp.v1.intf.*; import oasis.names.tc.wsrp.v1.types.PortletDescription; import oasis.names.tc.wsrp.v1.types.RegistrationContext; import oasis.names.tc.wsrp.v1.types.RegistrationData; import oasis.names.tc.wsrp.v1.types.RegistrationState; import oasis.names.tc.wsrp.v1.types.ReturnAny; import oasis.names.tc.wsrp.v1.types.ServiceDescription; import oasis.names.tc.wsrp.v1.types.GetServiceDescription; import oasis.names.tc.wsrp.v1.types.ModifyRegistration; import oasis.names.tc.wsrp.v1.wsdl.WSRPService; import org.apache.wsrp4j.commons.consumer.interfaces.producer.Producer; import org.apache.wsrp4j.commons.exception.ErrorCodes; import org.apache.wsrp4j.commons.exception.WSRPException; import org.apache.wsrp4j.commons.exception.WSRPXHelper; import org.apache.wsrp4j.commons.util.ParameterChecker; import org.apache.wsrp4j.commons.util.impl.StateChangedServiceImpl; /** * A consumer representation of a WSRP-producer providing WSRP-portlets. * Generally a producer can expose up to four WSRP-Interfaces. These interfaces * are Markup-, Service Description-,Registration- and * WSRPPortlet Management Interface. Whereas the Registration- and * Portlet Management Interface are optional. * * @see Producer * @version $Id: ProducerImpl.java 405796 2006-05-10 16:48:00Z dlouzan $ **/ public class ProducerImpl extends StateChangedServiceImpl implements Producer { private static Log log = LogFactory.getLog(ProducerImpl.class); // ID and misc. infos private String name; private String producerID; private String description; // URL's of the WSRP interfaces private String registrationURL; private String serviceDescriptionURL; private String markupURL; private String portletManagementURL; // Registration private boolean registrationRequired = false; private RegistrationContext registrationContext; private RegistrationData consumerRegData; // Service and portlet description private ServiceDescription serviceDescription; private Hashtable portletDesc; // Stubs private WSRPV1ServiceDescriptionPortType serviceDescriptionInterface; private WSRPV1RegistrationPortType registrationInterface; private WSRPV1PortletManagementPortType portletManagementInterface; // Parameter checker private ParameterChecker checker; /** * Default Constructor should not be used directly. But is * required for persistence support by castor. **/ public ProducerImpl() { this.portletDesc = new Hashtable(); checker = new ParameterChecker(); } /** * This constructor can be used to create a new producer object **/ public ProducerImpl(String producerID, String markupURL, String serviceDescriptionURL) throws WSRPException { this(); this.producerID = producerID; if (markupURL != null) { this.markupURL = markupURL; } else { WSRPXHelper.throwX(log, ErrorCodes.MISSING_MARKUP_PORT); } if (serviceDescriptionURL != null) { this.serviceDescriptionURL = serviceDescriptionURL; initServiceDescInterface(serviceDescriptionURL); } else { WSRPXHelper.throwX(log, ErrorCodes.MISSING_SERVICE_DESC_PORT); } } /** * This constructor can be used to create a new producer object **/ public ProducerImpl( String producerID, String markupURL, String serviceDescriptionURL, String registrationURL, String portletManagementURL, RegistrationData registrationData) throws WSRPException { this(producerID, markupURL, serviceDescriptionURL); if (registrationURL != null) { initRegistrationInterface(registrationURL); this.registrationURL = registrationURL; this.consumerRegData = registrationData; } if (portletManagementURL != null) { this.portletManagementURL = portletManagementURL; initPortletManagementInterface(portletManagementURL); } } /** * Initialize the service description interface of the producer. * * @param serviceDescriptionURL The URL of the producers service * description interface **/ public void initServiceDescInterface(String serviceDescriptionURL) throws WSRPException { // just in case this has not been done before and for castor persistence this.serviceDescriptionURL = serviceDescriptionURL; try { WSRPService service = new WSRPService(new URL(serviceDescriptionURL)); serviceDescriptionInterface = service.getWSRPServiceDescriptionService(); } catch (java.net.MalformedURLException urlEx) { WSRPXHelper.throwX(log, ErrorCodes.INVALID_URL_OF_SERVICE_DESC_PORT, urlEx); } catch (Exception xmlEx) { WSRPXHelper.throwX(log, ErrorCodes.INIT_OF_SERVICE_DESC_PORT_FAILED, xmlEx); } } /** * Initialize the registration interface of the producer. * * @param registrationURL The URL of the producers registration interface **/ public void initRegistrationInterface(String registrationURL) throws WSRPException { // just in case this has not been done before and for castor persistence this.registrationURL = registrationURL; try { WSRPService service = new WSRPService(new URL(registrationURL)); registrationInterface = service.getWSRPRegistrationService(); } catch (java.net.MalformedURLException urlEx) { WSRPXHelper.throwX(log, ErrorCodes.INVALID_URL_OF_REGISTRATION_PORT, urlEx); } catch (Exception xmlEx) { WSRPXHelper.throwX(log, ErrorCodes.INIT_OF_SERVICE_DESC_PORT_FAILED, xmlEx); } } /** * Get the URL of the producers service description interface. * * @return URL of the service description interface. **/ public String getServiceDescriptionInterfaceEndpoint() { return this.serviceDescriptionURL; } /** * Set the URL of the producers service description interface. * * @param url URL of the service description interface. **/ public void setServiceDescriptionInterfaceEndpoint(String url) { serviceDescriptionURL = url; stateChanged(); } /** * Get the URL of the producers registration interface. * * @return URL of the registration interface. **/ public String getRegistrationInterfaceEndpoint() { return registrationURL; } /** * Set the URL of the producers registration interface. * * @param url URL of the registration interface. **/ public void setRegistrationInterfaceEndpoint(String url) { registrationURL = url; stateChanged(); } /** * Get the ID of the producer. * * @return The ID of the producer **/ public String getID() { return producerID; } /** * Set the ID of the producer to he given value. * * @param id ID of the producer. **/ public void setID(String id) { producerID = id; stateChanged(); } /** * Get the name of the producer. * * @return The name of the producer **/ public String getName() { return name; } /** * Set the name of the producer. * * @param name The name of the producer **/ public void setName(String name) { this.name = name; stateChanged(); } /** * Get a description of the producer. * * @return A description of the producer **/ public String getDescription() { return this.description; } /** * Set a description of the producer. * * @param description Some descriptive information about the producer **/ public void setDescription(String description) { this.description = description; stateChanged(); } /** * Indicates wether or not the producer requires consumer registration. * * @return True if consumer registration is required. **/ public boolean isRegistrationRequired() { return this.registrationRequired; } /** * Define if the producer requires in-band registration or not. * * @param registrationRequired True if the producer requires in-band * registration **/ public void setIsRegistrationRequired(boolean registrationRequired) { this.registrationRequired = registrationRequired; stateChanged(); } /** * Get the registration data the consumer uses to register at this producer. * * @return The consumer registration data **/ public RegistrationData getRegistrationData() { return consumerRegData; } /** * Set the registration the consumer uses the register at this producer. * * @param regData The registration data which is used to register at this * producer **/ public void setRegistrationData(RegistrationData regData) { consumerRegData = regData; stateChanged(); } /** * Get the current registration context of the consumer registered at this * producer or null * if no registration is required or happend so far. * * @return The current registration context of the consumer at this * producer or null. **/ public RegistrationContext getRegistrationContext() { return this.registrationContext; } /** * Set the registration context. * * @param registrationContext The registration context of a consumer * registered at the producer. **/ public void setRegistrationContext( RegistrationContext registrationContext) { if (registrationContext != null) { this.registrationContext = registrationContext; stateChanged(); } } /** * Same as getServiceDescription(false) **/ public ServiceDescription getServiceDescription() throws WSRPException { return getServiceDescription(false); } /** * Get the service description of the producer * * @param newRequest If set to true a new request is send to the producer * otherwise a cached service description * is used if available * * @return Service description of the producer **/ public ServiceDescription getServiceDescription(boolean newRequest) throws WSRPException { if (this.serviceDescription == null || newRequest) { GetServiceDescription request = new GetServiceDescription(); if (registrationContext != null) { request.setRegistrationContext(registrationContext); } // TODO: Set desired locales which are supported by the consumer //request.setDesiredLocales(new String[]{Constants.LOCALE_EN_US, // Constants.LOCALE_DE_DE}); // for now request all locales request.getDesiredLocales().clear(); ServiceDescription response = null; try { response = serviceDescriptionInterface. getServiceDescription(request); if (response != null) { try { checker.check(response); } catch (MissingParameters wsrpFault) { WSRPXHelper.handleWSRPFault(log, wsrpFault); } if (registrationContext == null && response.isRequiresRegistration()) { register(consumerRegData); getServiceDescription(true); } else { setServiceDescription(response); } } else { WSRPXHelper.throwX(log, ErrorCodes.INVALID_SERVICE_DESCRIPTION); } } catch (InvalidRegistration invalidReg) { // producer did not accept the registration // lets try it again register(consumerRegData); getServiceDescription(true); } catch (OperationFailed wsrpFault) { WSRPXHelper.handleWSRPFault(log, wsrpFault); } } return this.serviceDescription; } /** * Get the portlet description of the portlet with the given handle from the * service description or null if the producer doesn't offer an portlet * with this handle in it's service description. * * @param portletHandle The portlet handle of the portlet * * @return The portlet description of the portlet with the given handle **/ public PortletDescription getPortletDescription(String portletHandle) throws WSRPException { PortletDescription desc = null; if (portletHandle != null) { if (serviceDescription == null) { // fetch a new portlet description from the producer getServiceDescription(); } desc = (PortletDescription)portletDesc.get(portletHandle); if (desc == null) { WSRPXHelper.throwX(log, ErrorCodes.INVALID_PORTLET_HANDLE); } } return desc; } /** * Set the service description. **/ public void setServiceDescription(ServiceDescription serviceDescription) { if (serviceDescription != null) { this.serviceDescription = serviceDescription; updatePortletDescriptions(serviceDescription); setIsRegistrationRequired( serviceDescription.isRequiresRegistration()); } } /** * Add an portlet description to the producer. This portlet description is * accessable through the portlet handle in the portlet description. If the * producer has already an portlet description with this portlet handle than * the old description will be overwritten. * * @param portletDescription New portlet description **/ public void addPortletDescription(PortletDescription portletDescription) { if (portletDescription != null) { this.portletDesc.put(portletDescription.getPortletHandle(), portletDescription); } } private void updatePortletDescriptions( ServiceDescription serviceDescription) { if (serviceDescription != null) { List<PortletDescription> offeredPortlets = serviceDescription.getOfferedPortlets(); if (offeredPortlets != null) { this.portletDesc.clear(); for (PortletDescription pd: offeredPortlets) { if (pd != null) { addPortletDescription(pd); } } } } } /** * Method establishes a relationship between consumer and producer. * * Note: A additional call of setRegistrationContext() is not neccesary * * @param registrationData Data which is used to register the consumer * * @return The registration context received by the producer **/ public RegistrationContext register(RegistrationData registrationData) throws WSRPException { if (registrationData != null && this.registrationInterface != null) { try { RegistrationContext regContext = registrationInterface.register(registrationData); checker.check(regContext, false); setRegistrationContext(regContext); } catch (OperationFailed operationFailed) { WSRPXHelper.handleWSRPFault(log, operationFailed); } catch (MissingParameters missingParameters) { WSRPXHelper.handleWSRPFault(log, missingParameters); } } else { // TODO: Either no registration data or producer does not support // in-band registration } return this.registrationContext; } /** * Can be used to modify the relationship between consumer and producer. * * Note: A additional call of setRegistrationContext() is not neccesary * * @param registrationData The new registration data * * @return New registration context **/ public RegistrationState modifyRegistration( RegistrationData registrationData) throws WSRPException { RegistrationState newState = null; try { if (registrationData != null && this.registrationInterface != null) { ModifyRegistration request = new ModifyRegistration(); if (registrationContext != null) { request.setRegistrationContext(registrationContext); } request.setRegistrationData(registrationData); newState = registrationInterface.modifyRegistration(request); getRegistrationContext().setRegistrationState( newState.getRegistrationState()); stateChanged(); } else { // TODO: Either no data or producer does not support in-band // registration } } catch (InvalidRegistration invalidRegistration) { WSRPXHelper.handleWSRPFault(log, invalidRegistration); } catch (OperationFailed operationFailed) { WSRPXHelper.handleWSRPFault(log, operationFailed); } catch (MissingParameters missingParameters) { WSRPXHelper.handleWSRPFault(log, missingParameters); } return newState; } /** * End an existing consumer producer relationship and remove the * registration context * * @return Can be anything **/ public ReturnAny deregister() throws WSRPException { ReturnAny any = null; try { if (registrationContext != null && this.registrationInterface != null) { any = registrationInterface.deregister( this.registrationContext); registrationContext = null; registrationRequired = false; stateChanged(); } else { // TODO: Either we aren't registered at the producer or // the producer does not support in-band registration } } catch (InvalidRegistration invalidRegistration) { WSRPXHelper.handleWSRPFault(log, invalidRegistration); } catch (OperationFailed operationFailed) { WSRPXHelper.handleWSRPFault(log, operationFailed); } return any; } /** * @see org.apache.wsrp4j.commons.consumer.interfaces.producer.Producer#getMarkupInterfaceEndpoint() */ public String getMarkupInterfaceEndpoint() { return markupURL; } /** * @see org.apache.wsrp4j.commons.consumer.interfaces.producer.Producer#setMarkupInterfaceEndpoint(java.lang.String) */ public void setMarkupInterfaceEndpoint(String url) { markupURL = url; stateChanged(); } /** * @see org.apache.wsrp4j.commons.consumer.interfaces.producer.Producer#getPortletManagementInterfaceEndpoint() */ public String getPortletManagementInterfaceEndpoint() { return portletManagementURL; } /** * @see org.apache.wsrp4j.commons.consumer.interfaces.producer.Producer#setPortletManagementInterfaceEndpoint(java.lang.String) */ public void setPortletManagementInterfaceEndpoint(String url) { portletManagementURL = url; stateChanged(); } public void initPortletManagementInterface(String portletManagementURL) throws WSRPException { final String MN = "initPortletManagementInterface"; // just in case this has not been done before and for castor persistence this.portletManagementURL = portletManagementURL; try { WSRPService service = new WSRPService(new URL(portletManagementURL)); portletManagementInterface = service.getWSRPPortletManagementService(); } catch (java.net.MalformedURLException urlEx) { WSRPXHelper.throwX( log, ErrorCodes.INVALID_URL_OF_PORTLET_MGMT_PORT, urlEx); } } public WSRPV1PortletManagementPortType getPortletManagementInterface() { return portletManagementInterface; } public WSRPV1RegistrationPortType getRegistrationInterface() { return registrationInterface; } public WSRPV1ServiceDescriptionPortType getServiceDescriptionInterface() { return serviceDescriptionInterface; } public boolean isPortletManagementInferfaceSupported() { if ( portletManagementURL != null ) { return true; } return false; } public boolean isRegistrationInterfaceSupported() { if ( registrationURL != null ) { return true; } return false; } }