/**
   * Constructor.
   *
   * @param clientAddress The client IP address.
   * @param clientPort The client port (remote).
   * @param serverPort The server port (local).
   */
  public IdentClient(String clientAddress, int clientPort, int serverPort) {
    Socket socket = null;

    if ((clientAddress != null) && (clientPort != -1) && (serverPort != -1)) {
      BufferedReader in = null;
      try {
        // Compose the IDENT request
        final StringBuilder sb = new StringBuilder();
        sb.append(clientPort).append(" , ").append(serverPort).append("\r\n");
        final String request = sb.toString();

        // Send the request to the remote server
        socket = new Socket();
        socket.setSoTimeout(SO_TIMEOUT);
        socket.connect(new InetSocketAddress(clientAddress, 113), CONNECT_TIMEOUT);
        socket.getOutputStream().write(StringUtils.getAsciiBytes(request));

        // Read the response
        in =
            new BufferedReader(new InputStreamReader(socket.getInputStream()), IoUtils.BUFFER_SIZE);
        final String response = in.readLine();

        // Parse the response
        if (response != null) {
          final StringTokenizer st = new StringTokenizer(response, ":");

          if (st.countTokens() >= 3) {
            // Skip the first token
            st.nextToken();

            // Get the command
            final String command = st.nextToken().trim();
            if (command.equalsIgnoreCase("USERID") && (st.countTokens() >= 2)) {
              // Get the host type
              this.hostType = st.nextToken().trim();

              // Get the remaining text as a user identifier
              this.userIdentifier = st.nextToken("").substring(1);
            }
          }
        }
      } catch (IOException ioe) {
        Context.getCurrentLogger().log(Level.FINE, "Unable to complete the IDENT request", ioe);
      } finally {
        try {
          // Always attempt to close the reader, therefore the socket
          if (in != null) {
            in.close();
          }
        } catch (IOException ioe) {
          Context.getCurrentLogger().log(Level.FINE, "Unable to close the socket", ioe);
        }
      }
    }
  }
  private static Resource getResource(
      CollectInfo collectInfo, Object restlet, String basePath, ChallengeScheme scheme) {
    Resource resource = new Resource();
    resource.setResourcePath(basePath);

    if (restlet instanceof Directory) {
      Directory directory = (Directory) restlet;
      resource.setName(directory.getName());
      resource.setDescription(directory.getDescription());
    }
    if (restlet instanceof ServerResource) {
      ServerResource serverResource = (ServerResource) restlet;
      resource.setName(serverResource.getName());
      resource.setDescription(serverResource.getDescription());
    }
    if (restlet instanceof DocumentedResource) {
      DocumentedResource documentedServerResource = (DocumentedResource) restlet;
      resource.setSections(documentedServerResource.getSections());
    } else if (collectInfo.isUseSectionNamingPackageStrategy()) {
      String sectionName = restlet.getClass().getPackage().getName();
      resource.getSections().add(sectionName);
    }

    if (StringUtils.isNullOrEmpty(resource.getName())) {
      String name = restlet.getClass().getSimpleName();
      if (name.endsWith(SUFFIX_SERVER_RESOURCE)
          && name.length() > SUFFIX_SERVER_RESOURCE.length()) {
        name = name.substring(0, name.length() - SUFFIX_SERVER_RESOURCE.length());
      }
      if (name.endsWith(SUFFIX_RESOURCE) && name.length() > SUFFIX_RESOURCE.length()) {
        name = name.substring(0, name.length() - SUFFIX_RESOURCE.length());
      }
      resource.setName(name);
    }

    Template template = new Template(basePath);
    for (String variable : template.getVariableNames()) {
      PathVariable pathVariable = new PathVariable();
      pathVariable.setName(variable);
      resource.getPathVariables().add(pathVariable);
    }

    if (scheme != null) {
      resource.setAuthenticationProtocol(scheme.getName());
    }

    return resource;
  }
 private static void completeOperationQueryParameter(
     Operation operation, MethodAnnotationInfo mai) {
   if (mai.getQuery() != null) {
     Form form = new Form(mai.getQuery());
     for (org.restlet.data.Parameter parameter : form) {
       QueryParameter queryParameter = new QueryParameter();
       queryParameter.setName(parameter.getName());
       queryParameter.setRequired(true);
       queryParameter.setDescription(
           StringUtils.isNullOrEmpty(parameter.getValue())
               ? ""
               : "Value: " + parameter.getValue());
       queryParameter.setDefaultValue(parameter.getValue());
       queryParameter.setAllowMultiple(false);
       operation.getQueryParameters().add(queryParameter);
     }
   }
 }
  public static void collectResource(
      CollectInfo collectInfo,
      ServerResource sr,
      String basePath,
      ChallengeScheme scheme,
      List<? extends IntrospectionHelper> introspectionHelper) {
    Resource resource = getResource(collectInfo, sr, basePath, scheme);

    // add operations
    ArrayList<Operation> operations = new ArrayList<>();

    List<AnnotationInfo> annotations =
        sr.isAnnotated() ? AnnotationUtils.getInstance().getAnnotations(sr.getClass()) : null;

    if (annotations != null) {
      for (AnnotationInfo annotationInfo : annotations) {
        if (annotationInfo instanceof MethodAnnotationInfo) {
          MethodAnnotationInfo methodAnnotationInfo = (MethodAnnotationInfo) annotationInfo;

          Method method = methodAnnotationInfo.getRestletMethod();

          Operation operation = getOperationFromMethod(method);

          if (StringUtils.isNullOrEmpty(operation.getName())) {
            operation.setName(methodAnnotationInfo.getJavaMethod().getName());
          }

          completeOperation(collectInfo, operation, methodAnnotationInfo, sr, introspectionHelper);

          for (IntrospectionHelper helper : introspectionHelper) {
            List<Class<?>> representationClasses =
                helper.processOperation(
                    resource, operation, sr.getClass(), methodAnnotationInfo.getJavaMethod());
            if (representationClasses != null && !representationClasses.isEmpty()) {
              for (Class<?> representationClazz : representationClasses) {
                TypeInfo typeInfo;
                try {
                  typeInfo = Types.getTypeInfo(representationClazz, null);
                } catch (UnsupportedTypeException e) {
                  LOGGER.warning(
                      "Could not add representation class "
                          + representationClazz.getName()
                          + ". "
                          + e.getMessage());
                  continue;
                }
                RepresentationCollector.addRepresentation(
                    collectInfo, typeInfo, introspectionHelper);
              }
            }
          }
          operations.add(operation);
        }
      }
      if (!operations.isEmpty()) {
        sortOperationsByMethod(operations);
        resource.setOperations(operations);
        addSectionsForResource(collectInfo, resource);
        collectInfo.addResource(resource);
      } else {
        LOGGER.warning("Resource " + resource.getName() + " has no methods.");
      }
    } else {
      LOGGER.warning("Resource " + resource.getName() + " has no methods.");
    }

    for (IntrospectionHelper helper : introspectionHelper) {
      helper.processResource(resource, sr.getClass());
    }
  }