Package com.sun.jini.tool.envcheck.plugins

Source Code of com.sun.jini.tool.envcheck.plugins.CheckCodebase$GetURLTask

/*
* 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 com.sun.jini.tool.envcheck.plugins;

import com.sun.jini.start.NonActivatableServiceDescriptor;
import com.sun.jini.start.ServiceDescriptor;
import com.sun.jini.start.SharedActivationGroupDescriptor;

import com.sun.jini.tool.envcheck.AbstractPlugin;
import com.sun.jini.tool.envcheck.Plugin;
import com.sun.jini.tool.envcheck.EnvCheck;
import com.sun.jini.tool.envcheck.Reporter;
import com.sun.jini.tool.envcheck.Reporter.Message;
import com.sun.jini.tool.envcheck.SubVMTask;

import java.io.InputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;

/**
* Plugin which performs a variety of checks on codebase components.  If not
* configured to perform service starter checks, the codebase is expected to be
* defined by the <code>java.rmi.server.codebase</code> system
* property. Otherwise, all of the codebases contained in the service
* descriptors of the service starter <code>Configuration</code> are examined
* (excepting <code>SharedActivationGroupDescriptors</code>, which do not have a
* codebase). First, an existence check is performed; the codebase string must
* be non-null and have length > 0 after white space is trimmed. Non-existence
* is reported as an error. Then the codebase is decomposed into tokens (URL
* strings). Each component in a codebase is checked for the following:
* <ul>
* <li>check for a valid URL. As a special case, an httpmd URL which
*     is invalid because the necessary protocol handler was not loaded
*     will result in the generation of an appropriate error message
*     and explanation. Further checks are not done for invalid URLs.
* <li>check that the host name is expressed using a fully qualified domain name
* <li>check for the use of md5 hashes in httpmd URLs
* <li>check the ability to resolve the host name to an address
* <li>check for a host name of 'localhost'
* <li>check for the ability to access (connect to) the URL
* </ul>
* Failure of the first or last checks are displayed as errors. Failure of
* the other checks are displayed as warnings.
*/
public class CheckCodebase extends AbstractPlugin {

    /** reference to the plugin container */
    EnvCheck envCheck;

    /**
     * Depending on whether service start checks are configured,
     * either check the codebase system property or all of the
     * <code>ServiceDescriptors</code> that are <code>instanceof</code>
     * <code>NonActivatableServiceDescriptor</code>.
     */
    public void run(EnvCheck envCheck) {
  this.envCheck = envCheck;
  String source;
  String codebase;
  if (envCheck.getDescriptors().length == 0) {
      source = getString("propsource");
      codebase = envCheck.getProperty("java.rmi.server.codebase");
      doChecks(null, null, source, codebase);
  } else {
      ServiceDescriptor[] sd = envCheck.getDescriptors();
      SharedActivationGroupDescriptor g = envCheck.getGroupDescriptor();
      for (int i = 0; i < sd.length; i++) {
    if (sd[i] instanceof NonActivatableServiceDescriptor) {
        NonActivatableServiceDescriptor d =
      (NonActivatableServiceDescriptor) sd[i];
        source = getString("desc") + " " + d.getImplClassName();
        codebase = d.getExportCodebase();
        doChecks(d, g, source, codebase);
    }
      }
  }
    }

    /**
     * Perform all of the checks on <code>codebase</code>.
     *
     * @param source a string describing the source of the codebase for
     *               use in report messages
     * @param codebase the codebase to check
     */
    private void doChecks(NonActivatableServiceDescriptor d,
        SharedActivationGroupDescriptor g,
        String source,
        String codebase)
    {
  if (checkExistance(source, codebase)) {
      StringTokenizer tok = new StringTokenizer(codebase);
      while (tok.hasMoreTokens()) {
    String urlToken = tok.nextToken();
    URL url = checkURL(d, g, source, urlToken);
    if (url != null) {
        checkForFQDomain(url, source);
        checkForMD5(url, source);
        checkForKnownHost(url, source);
        checkForLocalHost(url, source);
        checkAccessibility(url, source);
    }
      }
  }
    }

    /**
     * Check for existence. <code>codebase</code> must be non-null
     * and have length > 0 after trimming whitespace.
     *
     * @param source identifies the source of the codebase
     * @param codebase the codebase to check
     * @return true if existence check is successful
     */
    private boolean checkExistance(String source, final String codebase) {
  Message message;
  boolean gotCodebase;
  if (codebase != null && codebase.trim().length() > 0) {
      message = new Message(Reporter.INFO,
          getString("codebaseIs") + " " + codebase,
          getString("existenceExp"));
      gotCodebase = true;
  } else {
      message = new Message(Reporter.INFO,
          getString("nocodebase"),
          getString("existenceExp"));
      gotCodebase = false;
  }
  Reporter.print(message, source);
  return gotCodebase;
    }

    /**
     * Check whether <code>urlToken</code> can be used to construct
     * a <code>URL</code> object. If a <code>MalformedURLException</code>
     * is thrown, check whether the protocol portion of the URL is
     * <code>httpmd:</code>. If so, check whether the protocol handler is
     * installed. If not, output an appropriate message. Otherwise, just
     * complain generally that the URL is malformed.
     *
     * @param source the source of the codebase
     * @param urlToken the codebase component to check
     * @return the corresponding URL object if successful, <code>null</code>
     *         otherwise
     */
    private URL checkURL(NonActivatableServiceDescriptor d,
       SharedActivationGroupDescriptor g,
       String source,
       final String urlToken)
    {
  Message message;
  URL url = null;
  String[] args = new String[]{urlToken};
  Object lobj = envCheck.launch(d, g, taskName("GetURLTask"), args);
  if (lobj instanceof URL) {
      url = (URL) lobj;
  } else if (lobj instanceof String) {
      String cause = (String) lobj;
      if (cause.equals("nohandler")) {
    message = new Message(Reporter.ERROR,
              getString("nohandler", urlToken),
              getString("httpmdExp"));
    Reporter.print(message, source);
    try {
        url = new URL(urlToken);
    } catch (MalformedURLException e) { // should never happen
        message = new Message(Reporter.ERROR,
            getString("badURL", urlToken),
            e,
            null);
        Reporter.print(message, source);
    }
      } else {
    message =
        new Message(Reporter.ERROR,
        getString("badURL", urlToken) + ": " + cause,
        null);
   
    Reporter.print(message, source);
      }
  } else {
      handleUnexpectedSubtaskReturn(lobj, source);
  }
  return url;
    }

    /**
     * Check the ability to resolve the host component of <code>url</code>
     * to an <code>InetAddress</code>. If successful, this method is silent.
     *
     * @param url the <code>URL</code> to check
     * @param source the source of the <code>URL</code>
     */
    private void checkForKnownHost(final URL url, String source) {
  try {
      InetAddress.getByName(url.getHost()).getCanonicalHostName();
  } catch (UnknownHostException e) {
      Message message = new Message(Reporter.ERROR,
            getString("noHost",
                url.getHost(),
                url),
            null);
      Reporter.print(message, source);
  }
    }

    /**
     * Check whether the host component of <code>url</code> resolves
     * to a loopback address.
     *
     * @param url the <code>URL</code> to check
     * @param source the source of the <code>URL</code>
     */
    private void checkForLocalHost(final URL url, String source) {
  try {
      if (InetAddress.getByName(url.getHost()).isLoopbackAddress()) {
    Message message = new Message(Reporter.WARNING,
                getString("usedLocalhost", url),
                getString("localhostExp"));
    Reporter.print(message, source);
      }
  } catch (Exception ignore) { // accessibility check handles this failure
  }
    }

    /**
     * Check the accessibility of the codebase <code>URL</code> by opening a
     * connection to it. This check fails if the <code>openConnection</code>
     * call or subsequent <code>getInputStream </code> call throws an
     * <code>IOException</code>, or if these calls do not complete within 5
     * seconds. These two failure modes result in different error messages
     * being output.
     *
     * @param url the <code>URL</code> to check
     * @param source the source of the <code>URL</code>
     */
    private void checkAccessibility(final URL url, String source) {
  Message message;
  URLAccessor accessor = new URLAccessor(url);
  Thread t = new Thread(accessor);
  t.setDaemon(true);
  t.start();
  try {
      t.join(5000, 0);
  } catch (Exception e) {
      e.printStackTrace();
  }
  if (t.isAlive()) {
      message = new Message(Reporter.ERROR,
          getString("noresponse", url),
          null);
  } else if (accessor.getException() == null) {
      message = new Message(Reporter.INFO,
          getString("available", url),
          null);
  } else {
      message = new Message(Reporter.ERROR,
          getString("unavailable", url),
          accessor.getException(),
          null);
  }
  Reporter.print(message, source);
    }

    /**
     * Check for a fully qualified host name. To be valid, the host
     * name must consist of at least two '.' separated tokens, and the
     * last token must be one of the well-known top level domain names,
     * or the last token must be a two character string which is assumed
     * to be a country code.
     *
     * @param url the <code>URL</code> to check
     * @param source the source of the <code>URL</code>
     */
    private void checkForFQDomain(final URL url, String source) {

  String[] topLevelDomains = {"aero", "biz", "com", "coop","edu",
            "gov", "info", "int", "mil","museum",
            "name", "net", "org", "pro"};
  String hostName = url.getHost();
  int lastDot = hostName.lastIndexOf('.');
  if (lastDot >= 0 && lastDot < hostName.length() - 1) {
      String tld = hostName.substring(lastDot + 1); // top level domain
      if (tld.length() == 2) {
    return;
      }
      for (int i = 0; i < topLevelDomains.length; i++) {
    if (tld.equals(topLevelDomains[i])) {
        return;
    }
      }
  }
  Message message = new Message(Reporter.WARNING,
              getString("unqualified", url.getHost()),
              getString("unqualifiedExp"));
  Reporter.print(message, source);
    }

    /**
     * Check for use of an MD5 httpmd URL. If the protocol of <code>url</code>
     * is httpmd, then the hash function identifier is parsed from the
     * file component of <code>url</code> and a string comparison is done.
     *
     * @param url the <code>URL</code> to check
     * @param source the source of the <code>URL</code>
     */
    private void checkForMD5(final URL url, String source) {
  if(! url.getProtocol().equalsIgnoreCase("httpmd")) {
      return;
  }
  // can assume hashcode is present, or url construction would have failed
  String target = url.getFile();
  int lastSemi = target.lastIndexOf(';');
  String hash = target.substring(lastSemi + 1);
  if (hash.startsWith("md5")) {
      Message message = new Message(Reporter.WARNING,
            getString("usesmd5", url),
            getString("usesmd5Exp"));
      Reporter.print(message, source);
  }
    }

    /**
     * A <code>Runnable</code> which attempts to open a <code>URL</code>
     * connection. If the attempt results in an exception being throw,
     * the exception is stored for later access by the invoker of the thread.
     */
    private class URLAccessor implements Runnable {

  URL url;
  Throwable exception = null;
 
  URLAccessor(URL url) {
      this.url = url;
  }

  public void run() {
      try {
    URLConnection con = url.openConnection();
    InputStream stream = con.getInputStream();
      } catch (IOException e) {
    exception = e;
      }
  }
 
  Throwable getException() {
      return exception;
  }
    } 

    public static class GetURLTask implements SubVMTask {

  public Object run(String[] args) {
      String urlToken = args[0];
      URL url;
      try {
    url = new URL(urlToken);
      } catch (MalformedURLException e) {
    int firstColon = urlToken.indexOf(':');
    if (firstColon > 0) {
        String protocol = urlToken.substring(0, firstColon);
        if (protocol.equalsIgnoreCase("httpmd")) {
      if (!httpmdHandlerInstalled()) {
          return "nohandler";
      }
        }
    }
    return e.getMessage();
      }
      return url;
  }

  private boolean httpmdHandlerInstalled() {
      try {
    new URL("httpmd://localhost/foo;sha=0");
      } catch (MalformedURLException e) {
    return false;
      }
      return true;
  }
    }
}
 
TOP

Related Classes of com.sun.jini.tool.envcheck.plugins.CheckCodebase$GetURLTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.