protected synchronized void unsubscribe() throws UnableToDestroySubscriptionFault {
    try {
      unregister();

    } catch (EndpointRegistrationException e) {
      UnableToDestroySubscriptionFaultType fault = new UnableToDestroySubscriptionFaultType();
      throw new UnableToDestroySubscriptionFault("Error unregistering endpoint", fault, e);
    }
    if (subscriberAddress != null && WsnProcessImpl.localtable != null) {
      String topicName = convertTopic(topic);
      Iterator<ListItem> iter = WsnProcessImpl.localtable.iterator();
      while (iter.hasNext()) {
        ListItem item = (ListItem) iter.next();
        if (item.getTopicName().equals(topicName)) iter.remove();
      }

      ListItem listCheck = null;

      for (ListItem listItem : WsnProcessImpl.localtable)
        if (listItem.getTopicName().equals(topicName)) listCheck = listItem;
      if (listCheck == null) {
        // NotifyObserver notify = new NotifyObserver(topicName,0);
        notifyObserver.setTopicName(topicName);
        notifyObserver.setKind(0);
        notifyObserver.addObserver(RtMgr.getInstance());
        notifyObserver.notifyMessage();
      }
    }
  }
  protected void validateSubscription(Subscribe subscribeRequest)
      throws InvalidFilterFault, InvalidMessageContentExpressionFault,
          InvalidProducerPropertiesExpressionFault, InvalidTopicExpressionFault,
          SubscribeCreationFailedFault, TopicExpressionDialectUnknownFault, TopicNotSupportedFault,
          UnacceptableInitialTerminationTimeFault, UnrecognizedPolicyRequestFault,
          UnsupportedPolicyRequestFault {
    // Check consumer reference
    consumerReference = subscribeRequest.getConsumerReference();
    // Check terminationTime
    if (subscribeRequest.getInitialTerminationTime() != null
        && !subscribeRequest.getInitialTerminationTime().isNil()
        && subscribeRequest.getInitialTerminationTime().getValue() != null) {
      String strTerminationTime = subscribeRequest.getInitialTerminationTime().getValue();
      terminationTime = validateInitialTerminationTime(strTerminationTime.trim());
    }
    // Check filter
    if (subscribeRequest.getFilter() != null) {
      for (Object f : subscribeRequest.getFilter().getAny()) {
        JAXBElement e = null;
        if (f instanceof JAXBElement) {
          e = (JAXBElement) f;
          f = e.getValue();
        }

        if (f instanceof TopicExpressionType) {
          if (!e.getName().equals(QNAME_TOPIC_EXPRESSION)) {
            InvalidTopicExpressionFaultType fault = new InvalidTopicExpressionFaultType();
            throw new InvalidTopicExpressionFault("Unrecognized TopicExpression: " + e, fault);
          }
          topic = (TopicExpressionType) f;
        } else if (f instanceof QueryExpressionType) {
          if (e != null && e.getName().equals(QNAME_PRODUCER_PROPERTIES)) {
            InvalidProducerPropertiesExpressionFaultType fault =
                new InvalidProducerPropertiesExpressionFaultType();
            throw new InvalidProducerPropertiesExpressionFault(
                "ProducerProperties are not supported", fault);
          } else if (e != null && e.getName().equals(QNAME_MESSAGE_CONTENT)) {
            if (contentFilter != null) {
              InvalidMessageContentExpressionFaultType fault =
                  new InvalidMessageContentExpressionFaultType();
              throw new InvalidMessageContentExpressionFault(
                  "Only one MessageContent filter can be specified", fault);
            }
            contentFilter = (QueryExpressionType) f;
            // Defaults to XPath 1.0
            if (contentFilter.getDialect() == null) {
              contentFilter.setDialect(XPATH1_URI);
            }
          } else {
            InvalidFilterFaultType fault = new InvalidFilterFaultType();
            throw new InvalidFilterFault(
                "Unrecognized filter: " + (e != null ? e.getName() : f), fault);
          }
        } else {
          InvalidFilterFaultType fault = new InvalidFilterFaultType();
          throw new InvalidFilterFault(
              "Unrecognized filter: " + (e != null ? e.getName() : f), fault);
        }
      }
    }
    // Check policy
    if (subscribeRequest.getSubscriptionPolicy() != null) {
      for (Object p : subscribeRequest.getSubscriptionPolicy().getAny()) {
        JAXBElement e = null;
        if (p instanceof JAXBElement) {
          e = (JAXBElement) p;
          p = e.getValue();
        }
        if (p instanceof UseRaw) {
          useRaw = true;
        } else {
          UnrecognizedPolicyRequestFaultType fault = new UnrecognizedPolicyRequestFaultType();
          throw new UnrecognizedPolicyRequestFault("Unrecognized policy: " + p, fault);
        }
      }
    }

    // Check subscriber address
    if (subscribeRequest.getSubscriberAddress() != null) {
      String value = subscribeRequest.getSubscriberAddress();
      if (WsnProcessImpl.localtable == null) {
        subscriberAddress = value.trim();
      } else {
        int TopicNameCounter = 0;
        int AddressCounter = 0;
        for (ListItem listItem : WsnProcessImpl.localtable) {
          if (listItem.getTopicName().equals(convertTopic(topic))) TopicNameCounter++;
          if (listItem.getSubscriberAddress().equals(value.trim())) AddressCounter++;
        }
        if ((AddressCounter == 0) || (TopicNameCounter == 0)) subscriberAddress = value.trim();
        else
          System.out.println(
              "subscribe failed! there is already a same subscription existed in wsn!");
      }
    }

    // Check all parameters
    if (consumerReference == null) {
      SubscribeCreationFailedFaultType fault = new SubscribeCreationFailedFaultType();
      throw new SubscribeCreationFailedFault("Invalid ConsumerReference: null", fault);
    }
    // TODO check we can resolve endpoint
    if (topic == null) {
      InvalidFilterFaultType fault = new InvalidFilterFaultType();
      throw new InvalidFilterFault("Must specify a topic to subscribe on", fault);
    }
    if (contentFilter != null && !contentFilter.getDialect().equals(XPATH1_URI)) {
      InvalidMessageContentExpressionFaultType fault =
          new InvalidMessageContentExpressionFaultType();
      throw new InvalidMessageContentExpressionFault(
          "Unsupported MessageContent dialect: '" + contentFilter.getDialect() + "'", fault);
    }
    if (terminationTime != null) {
      UnacceptableInitialTerminationTimeFaultType fault =
          new UnacceptableInitialTerminationTimeFaultType();
      throw new UnacceptableInitialTerminationTimeFault(
          "InitialTerminationTime is not supported", fault);
    }
  }