/* * Copyright (C) 2014 KAIST * @author Wondeuk Yoon <wdyoon@resl.kaist.ac.kr> * * Copyright (C) 2007 ETH Zurich * * This file is part of Fosstrak (www.fosstrak.org). * * Fosstrak is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * Fosstrak is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with Fosstrak; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ package org.fosstrak.ale.server.cc.impl; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import org.apache.log4j.Logger; import org.fosstrak.ale.exception.CCSpecValidationException; import org.fosstrak.ale.exception.DuplicateNameException; import org.fosstrak.ale.exception.DuplicateSubscriptionException; import org.fosstrak.ale.exception.ImplementationException; import org.fosstrak.ale.exception.InvalidURIException; import org.fosstrak.ale.exception.NoSuchNameException; import org.fosstrak.ale.exception.NoSuchSubscriberException; import org.fosstrak.ale.exception.SecurityException; import org.fosstrak.ale.server.ALEApplicationContext; import org.fosstrak.ale.server.ALESettings; import org.fosstrak.ale.server.ac.ALEACImpl; import org.fosstrak.ale.server.cc.ALECC; import org.fosstrak.ale.server.cc.ReportsGenerator; import org.fosstrak.ale.server.cc.impl.type.ReportsGeneratorsProvider; import org.fosstrak.ale.server.persistence.RemoveConfig; import org.fosstrak.ale.server.persistence.WriteConfig; import org.fosstrak.ale.server.impl.type.InputGeneratorProvider; import org.fosstrak.ale.server.readers.LogicalReader; import org.fosstrak.ale.server.readers.LogicalReaderManager; import org.fosstrak.ale.server.readers.rp.InputGenerator; import org.fosstrak.ale.xsd.ale.epcglobal.CCReports; import org.fosstrak.ale.xsd.ale.epcglobal.CCSpec; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * This class represents the application level events interface. * All ale operations are executed by this class. * * @author regli * @author swieland * @author haennimi * @author benoit.plomion@orange.com * @author Wondeuk Yoon */ @Service("alecc") public class ALECCImpl implements ALECC { /** logger. */ private static final Logger LOG = Logger.getLogger(ALECCImpl.class); /** set of input generators which deliver the tag event inputs. */ private InputGeneratorProvider inputGenerators = new InputGeneratorProvider(); private ReportsGeneratorsProvider reportGeneratorsProvider = new ReportsGeneratorsProvider(); /** indicates if the ale is ready or not. */ private boolean isReady = false; /** prefix for name of report generators which are created by immediate command. */ private static final String REPORT_GENERATOR_NAME_PREFIX = "ReportGenerator_"; /** index for name of report generator which are created by immediate command. */ private long nameCounter = 0; //@Autowired //private LogicalReaderManager logicalReaderManager; private static int AccessSpecCounter = 11; // autowired //private RemoveConfig persistenceRemoveAPI; //TODO: wdyoon // autowired //private WriteConfig persistenceWriteAPI; //TODO: wdyoon private String authScope = "ALECC"; @Autowired private ALEACImpl aleac; public ALEACImpl getAleac() { return aleac; } public void setAleac(ALEACImpl aleac) { this.aleac = aleac; } // autowired private ALESettings aleSettings; /** * setup the ALE directly after the construction of the bean.<br/> * <strong>NOTICE:</strong> Do not depend on initializer methods of other autowired components (like logical reader manager) * as the order of the initializer methods on the injected beans is not preset -> thus, the * injected bean might already be present in the ale, but not initialized (call postconstruct) yet. */ @PostConstruct public void initialize() { LOG.debug("initializing ALECC."); if (isReady) { LOG.debug("ALECC already initialized - abort instruction."); return; } isReady = false; reportGeneratorsProvider.clear(); inputGenerators.clear(); isReady = true; LOG.info("ALECC initialized"); } @Override public boolean isReady() { return isReady; } @Override public void define(String specName, CCSpec spec) throws DuplicateNameException, CCSpecValidationException, ImplementationException, SecurityException { aleac.checkAccess(authScope, Thread.currentThread().getStackTrace()[1].getMethodName()); if (reportGeneratorsProvider.containsKey(specName)) { LOG.debug("spec already defined: " + specName); throw new DuplicateNameException("CCSpec already defined with name: " + specName); } reportGeneratorsProvider.put(specName, reportGeneratorsProvider.createNewReportGenerator(specName, spec)); //persistenceWriteAPI.writeCCSpec(specName, spec); //TODO: wdyoon } @Override public void undefine(String specName) throws NoSuchNameException { throwNoSuchNameExceptionIfNoSuchSpec(specName); CCSpec ccspec = reportGeneratorsProvider.get(specName).getCCSpec(); LogicalReaderManager logicalReaderManager = ALEApplicationContext.getBean(LogicalReaderManager.class); LOG.debug("Recovery ACCESSSPEC of logicalReaders"); // get LogicalReaderStubs if (ccspec.getLogicalReaders() != null) { List<String> logicalReaderNames = ccspec.getLogicalReaders().getLogicalReader(); for (String logicalReaderName : logicalReaderNames) { //LOG.debug("retrieving logicalReader " + logicalReaderName); LogicalReader logicalReader = logicalReaderManager.getLogicalReader(logicalReaderName); if (logicalReader != null) { LOG.debug("Delete ACCESSSPEC from logicalReader : " + logicalReader.getName()); logicalReader.DELETEACCESSSPEC(); logicalReader.recoveryACCESSSPEC3(); } } } else { LOG.error("CCSpec contains no readers"); } reportGeneratorsProvider.remove(specName); //persistenceRemoveAPI.removeECSpec(specName); //TODO: wdyoon } @Override public CCSpec getCCSpec(String specName) throws NoSuchNameException { throwNoSuchNameExceptionIfNoSuchSpec(specName); return reportGeneratorsProvider.get(specName).getCCSpec(); } @Override public String[] getCCSpecNames() { return reportGeneratorsProvider.keySet().toArray(new String[0]); } @Override public void subscribe(String specName, String notificationURI) throws NoSuchNameException, InvalidURIException, DuplicateSubscriptionException { throwNoSuchNameExceptionIfNoSuchSpec(specName); reportGeneratorsProvider.get(specName).subscribe(notificationURI); //persistenceWriteAPI.writeECSpecSubscriber(specName, notificationURI); //TODO: wdyoon } @Override public void unsubscribe(String specName, String notificationURI) throws NoSuchNameException, NoSuchSubscriberException, InvalidURIException { throwNoSuchNameExceptionIfNoSuchSpec(specName); reportGeneratorsProvider.get(specName).unsubscribe(notificationURI); //persistenceRemoveAPI.removeECSpecSubscriber(specName, notificationURI); //TODO: wdyoon } @Override public CCReports poll(String specName) throws NoSuchNameException { throwNoSuchNameExceptionIfNoSuchSpec(specName); return poll(reportGeneratorsProvider.get(specName)); } @Override public CCReports immediate(CCSpec spec) throws CCSpecValidationException, ImplementationException { try { return poll(reportGeneratorsProvider.createNewReportGenerator(getNextReportGeneratorName(), spec)); } catch (NoSuchNameException e) { throw new ImplementationException("immediate failed"); } } @Override public String[] getSubscribers(String specName) throws NoSuchNameException { throwNoSuchNameExceptionIfNoSuchSpec(specName); return reportGeneratorsProvider.get(specName).getSubscribers().toArray(new String[0]); } @Override public final String getStandardVersion() { LOG.debug("getStandardVersion"); return aleSettings.getAleCCStandardVersion(); } @Override public final String getVendorVersion() { LOG.debug("getVendorVersion"); return aleSettings.getVendorVersion(); } @Override public void close() { LOG.info("Close ALE."); // remove input generators for (InputGenerator inputGenerator : inputGenerators) { inputGenerator.remove(); } } private CCReports poll(ReportsGenerator reportGenerator) throws NoSuchNameException { CCReports reports = null; reportGenerator.poll(); try { synchronized (reportGenerator) { reports = reportGenerator.getPollCCReports(); while (reports == null) { reportGenerator.wait(); reports = reportGenerator.getPollCCReports(); } } } catch (InterruptedException e) { LOG.debug("got interrupted."); } return reports; } /** * This method returns a name for a report generator which is created by a immediate command. * * @return name for input generator */ private String getNextReportGeneratorName() { return REPORT_GENERATOR_NAME_PREFIX + (nameCounter++); } @Override public Map<String, ReportsGenerator> getReportGenerators() { return reportGeneratorsProvider; } /** * throws an exception if the given specification name is not existing. * @param specName the name of the specification to verify. * @throws NoSuchNameException when name not existing. */ protected void throwNoSuchNameExceptionIfNoSuchSpec(String specName) throws NoSuchNameException { if (!reportGeneratorsProvider.containsKey(specName)) { throw new NoSuchNameException("No CCSpec with such name defined: " + specName); } } /** * allow to inject a new ALESettings. * @param aleSettings the new ALESettings to be used. */ @Autowired public void setAleSettings(ALESettings aleSettings) { this.aleSettings = aleSettings; } /** * allow to inject a new report generator provider. * @param reportGeneratorsProvider the new report generator provider. */ public void setReportGeneratorsProvider(ReportsGeneratorsProvider reportGeneratorsProvider) { this.reportGeneratorsProvider = reportGeneratorsProvider; } /** * allow to inject a new input generator provider. * @param inputGenerators the new input generator provider. */ public void setInputGenerators(InputGeneratorProvider inputGenerators) { this.inputGenerators = inputGenerators; } /** * allow to inject the persistence delete API. * @param persistenceRemoveAPI the persistence delete API. */ //@Autowired public void setPersistenceRemoveAPI(RemoveConfig persistenceRemoveAPI) { //this.persistenceRemoveAPI = persistenceRemoveAPI; //TODO: wdyoon } /** * allow to inject the persistence write API. * @param persistenceWriteAPI the persistence write API. */ //@Autowired public void setPersistenceWriteAPI(WriteConfig persistenceWriteAPI) { //this.persistenceWriteAPI = persistenceWriteAPI; //TODO: wdyoon } public static int getAccessSpecCounter() { return AccessSpecCounter; } public static void setAccessSpecCounter(int accessSpecCounter) { AccessSpecCounter = accessSpecCounter; } }