001package org.apache.turbine.services.uniqueid;
002
003
004import java.nio.charset.StandardCharsets;
005
006/*
007 * Licensed to the Apache Software Foundation (ASF) under one
008 * or more contributor license agreements.  See the NOTICE file
009 * distributed with this work for additional information
010 * regarding copyright ownership.  The ASF licenses this file
011 * to you under the Apache License, Version 2.0 (the
012 * "License"); you may not use this file except in compliance
013 * with the License.  You may obtain a copy of the License at
014 *
015 *   http://www.apache.org/licenses/LICENSE-2.0
016 *
017 * Unless required by applicable law or agreed to in writing,
018 * software distributed under the License is distributed on an
019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020 * KIND, either express or implied.  See the License for the
021 * specific language governing permissions and limitations
022 * under the License.
023 */
024
025
026import java.security.MessageDigest;
027import java.util.concurrent.atomic.AtomicInteger;
028
029import org.apache.commons.codec.binary.Base64;
030import org.apache.logging.log4j.LogManager;
031import org.apache.logging.log4j.Logger;
032import org.apache.turbine.Turbine;
033import org.apache.turbine.services.InitializationException;
034import org.apache.turbine.services.TurbineBaseService;
035import org.apache.turbine.util.GenerateUniqueId;
036
037/**
038 * <p> This is an implementation of {@link UniqueIdService}.
039 *
040 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
041 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
042 * @version $Id$
043 */
044public class TurbineUniqueIdService
045        extends TurbineBaseService
046        implements UniqueIdService
047{
048    /** Logging */
049    private static final Logger log = LogManager.getLogger(TurbineUniqueIdService.class);
050
051    /** The identifier of this instance of turbine. */
052    private static String turbineId = "UNKNOWN";
053
054    private static String turbineURL = "UNKNOWN";
055
056    private static final AtomicInteger counter = new AtomicInteger();
057
058
059    /**
060     * <p> Initializes the service upon first Turbine.doGet()
061     * invocation.
062     */
063    @Override
064    public void init()
065            throws InitializationException
066    {
067        try
068        {
069            counter.set(0);
070
071            // This might be a problem if the unique Id Service runs
072            // before Turbine got its first request. In this case,
073            // getDefaultServerData will return just a dummy value
074            // which is the same for all instances of Turbine.
075            //
076            // TODO This needs definitely further working.
077            turbineURL = Turbine.getDefaultServerData().toString();
078
079            MessageDigest md = MessageDigest.getInstance("MD5");
080            byte [] bytesId = md.digest(turbineURL.getBytes(StandardCharsets.UTF_8));
081            turbineId = new String(Base64.encodeBase64(bytesId),
082                    StandardCharsets.UTF_8);
083
084            log.info("This is Turbine instance running at: {}", turbineURL);
085            log.info("The instance id is #{}", turbineId);
086            setInit(true);
087        }
088        catch (Exception e)
089        {
090            throw new InitializationException(
091                    "Could not initialize TurbineUniqueId Service", e);
092        }
093    }
094
095    /**
096     * <p> Writes a message to the log upon system shutdown.
097     */
098    @Override
099    public void shutdown()
100    {
101        log.info("Turbine instance running at {} shutting down.", turbineURL);
102    }
103
104    /**
105     * <p> Returns an identifier of this Turbine instance that is unique
106     * both on the server and worldwide.  This identifier is computed
107     * as an MD5 sum of the URL (including schema, address, port if
108     * different that 80/443 respectively, context and servlet name).
109     * There is an overwhelming probability that this id will be
110     * different that all other Turbine instances online.
111     *
112     * @return A String with the instance identifier.
113     */
114    @Override
115    public String getInstanceId()
116    {
117        return turbineId;
118    }
119
120    /**
121     * <p> Returns an identifier that is unique within this turbine
122     * instance, but does not have random-like appearance.
123     *
124     * @return A String with the non-random looking instance
125     * identifier.
126     */
127    @Override
128    public String getUniqueId()
129    {
130        int current = counter.getAndIncrement();
131        String id = Integer.toString(current);
132
133        // If you manage to get more than 100 million of ids, you'll
134        // start getting ids longer than 8 characters.
135        if (current < 100000000)
136        {
137            id = ("00000000" + id).substring(id.length());
138        }
139        return id;
140    }
141
142    /**
143     * <p> Returns a unique identifier that looks like random data.
144     *
145     * @return A String with the random looking instance identifier.
146     */
147    @Override
148    public String getPseudorandomId()
149    {
150        return GenerateUniqueId.getIdentifier();
151    }
152}